package com.example.springcloud.order.service.impl;

import com.example.springcloud.order.dto.OrderDTO;
import com.example.springcloud.order.entity.Order;
import com.example.springcloud.order.enums.OrderStatus;
import com.example.springcloud.order.feign.AccountServiceFeign;
import com.example.springcloud.order.feign.StorageServiceFeign;
import com.example.springcloud.order.mapper.OrderMapper;
import com.example.springcloud.order.service.OrderService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 订单服务实现 - AT 模式
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private StorageServiceFeign storageServiceFeign;

    @Autowired
    private AccountServiceFeign accountServiceFeign;

    /**
     * 创建订单 - Seata AT 模式
     * AT 模式是 Seata 的默认模式，基于本地事务的两阶段提交
     * 优点：业务无侵入，自动生成反向 SQL
     * 缺点：依赖数据库的本地事务，性能相对较低
     */
    @Override
    @GlobalTransactional(name = "create-order-at", rollbackFor = Exception.class)
    public Order createOrderAT(OrderDTO orderDTO) {
        log.info("========开始创建订单 AT 模式========");
        log.info("全局事务 XID: {}", RootContext.getXID());

        // 1. 创建订单（本地事务）
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        order.setMoney(orderDTO.getMoney());
        order.setStatus(OrderStatus.CREATING.getCode());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        orderMapper.insert(order);
        log.info("订单创建成功，订单ID: {}", order.getId());

        // 2. 扣减库存（远程调用）
        log.info("调用库存服务扣减库存");
        storageServiceFeign.deduct(orderDTO.getProductId(), orderDTO.getCount());
        log.info("库存扣减成功");

        // 3. 扣减账户余额（远程调用）
        log.info("调用账户服务扣减余额");
        accountServiceFeign.deduct(orderDTO.getUserId(), orderDTO.getMoney());
        log.info("余额扣减成功");

        // 4. 更新订单状态为已完成
        order.setStatus(OrderStatus.FINISHED.getCode());
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
        log.info("订单状态更新为已完成");

        log.info("========订单创建完成 AT 模式========");
        return order;
    }

    /**
     * 创建订单 - Seata XA 模式
     * XA 模式基于数据库的 XA 协议，提供强一致性保证
     * 优点：强一致性，数据库原生支持
     * 缺点：性能相对较低，需要数据库支持 XA
     */
    @Override
    @GlobalTransactional(name = "create-order-xa", rollbackFor = Exception.class)
    public Order createOrderXA(OrderDTO orderDTO) {
        log.info("========开始创建订单 XA 模式========");
        log.info("全局事务 XID: {}", RootContext.getXID());

        // XA 模式的流程与 AT 模式类似，但使用数据库的 XA 协议
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        order.setMoney(orderDTO.getMoney());
        order.setStatus(OrderStatus.CREATING.getCode());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        orderMapper.insert(order);
        log.info("订单创建成功，订单ID: {}", order.getId());

        // 2. 扣减库存（远程调用 - XA 模式）
        log.info("调用库存服务扣减库存 - XA 模式");
        storageServiceFeign.deductXa(orderDTO.getProductId(), orderDTO.getCount());
        log.info("库存扣减成功");

        // 3. 扣减账户余额（远程调用 - XA 模式）
        log.info("调用账户服务扣减余额 - XA 模式");
        accountServiceFeign.deductXa(orderDTO.getUserId(), orderDTO.getMoney());
        log.info("余额扣减成功");

        // 4. 更新订单状态为已完成
        order.setStatus(OrderStatus.FINISHED.getCode());
        order.setUpdateTime(LocalDateTime.now());
        orderMapper.updateById(order);
        log.info("订单状态更新为已完成");

        log.info("========订单创建完成 XA 模式========");
        return order;
    }

    /**
     * 创建订单 - 测试回滚场景（SQL 成功执行后回滚）
     * 用于测试 undo_log 表的 Before Image 功能
     */
    @Override
    @GlobalTransactional(name = "create-order-rollback-test", rollbackFor = Exception.class)
    public Order createOrderRollbackTest(OrderDTO orderDTO) {
        log.info("========开始创建订单 - 回滚测试========");
        log.info("全局事务 XID: {}", RootContext.getXID());

        // 1. 创建订单（成功执行）
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        order.setMoney(orderDTO.getMoney());
        order.setStatus(OrderStatus.CREATING.getCode());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        orderMapper.insert(order);
        log.info("订单创建成功，订单ID: {}", order.getId());

        // 2. 扣减库存（成功执行）
        log.info("调用库存服务扣减库存");
        storageServiceFeign.deduct(orderDTO.getProductId(), orderDTO.getCount());
        log.info("库存扣减成功");

        // 3. 扣减账户余额（成功执行）
        log.info("调用账户服务扣减余额");
        accountServiceFeign.deduct(orderDTO.getUserId(), orderDTO.getMoney());
        log.info("余额扣减成功");

        // 4. 模拟业务异常，触发回滚
        log.info("模拟业务异常，触发回滚");
        throw new RuntimeException("模拟业务异常，测试 undo_log 回滚功能");
    }
}

